home *** CD-ROM | disk | FTP | other *** search
- /* Changed to support COFF format used by MIPS. Assumes Ultrix 4.1 or more recent. */
- /* All changes are ifdef'd mips, so can use for sparc, etc. R. Osborne July 9/91 */
-
- /*
- * D Y N L O A D . C
- *
- * This file contains functions to help dynamically load foreign UNIX files
- * into a running T process.
- *
- * written by Dorab Patel <dorab@neptune.cs.ucla.edu>
- * December 24, 1986
- * Copyright Dorab Patel (C) 1986
- * Permission is given to distribute this software free to anyone
- * using it for a non-commercial purpose. Comments/bug reports/fixes
- * are encouraged.
- *
- * $Revision: 1.1 $
- *
- * $Log: dynload.c,v $
- * Revision 1.1 86/12/24 18:20:44 dorab
- * Initial Revision
- *
- */
- #ifndef lint
- static char RCSid[] = "@(#)$Header: dynload.c,v 1.1 86/12/24 18:20:44 dorab UCLA $ (Exp)";
- #endif
-
- #include <stdio.h> /* for obvious reasons */
- #ifdef mips
- #include <sys/exec.h> /* on Ultrix RISC, sys/exec.h defines the BSD-like exec structure for a.out format */
- /* Following copied from <a.out.h>: */
- #define A_MAGIC1 0407 /* normal */
- #define A_MAGIC0 0401 /* lpd (UNIX/RT) */
- #define A_MAGIC2 0410 /* read-only text */
- #define A_MAGIC3 0411 /* separated I&D */
- #define A_MAGIC4 0405 /* overlay */
- #define A_MAGIC5 0437 /* system overlay, separated I&D */
-
- /* in invocation of BADMAG macro, argument should not be a function. */
-
- #define BADMAG(X) (X.a_magic != A_MAGIC1 &&\
- X.a_magic != A_MAGIC2 &&\
- X.a_magic != A_MAGIC3 &&\
- X.a_magic != A_MAGIC4 &&\
- X.a_magic != A_MAGIC5 &&\
- X.a_magic != A_MAGIC0)
- #else
- #include <a.out.h> /* for obvious reasons */
- #endif
- #include <sys/types.h> /* for caddr_t */
- #include <strings.h> /* for strlen */
-
- /*
- * dont turn this on unless you want copious debugging.
- * it may also have unwanted interactions with sbrk.
- */
- #undef DEBUG
-
-
- /*
- * alloca is used by default for efficiency. if you need to use
- * malloc, then define USE_MALLOC
- */
- #undef USE_MALLOC
-
- /* forward declarations */
- caddr_t sbrk();
- char *sprintf();
- #ifdef USE_MALLOC
- char *malloc();
- #else ~USE_MALLOC
- char *alloca();
- #endif ~USE_MALLOC
-
- /*
- * loadhelp takes an object file (objFile), and loads it
- * into the current process, using relocation information found in the
- * namelist of relocFile. In the process, it will create
- * tmpFile, which has all the current relocation info and which can
- * be used for a subsequent load. In addition, libString
- * is used to search any required libraries.
- * otherString can be used for other ld arguments.
- * Returns 0 if all ok, >0 otherwise.
- * It closes all files it has opened and unlinks the temp file
- * if there has been an error.
- *
- * TODO:
- * do i need to round up the text/data sizes to word boundaries ?
- */
-
- /*
- * the sprintf string for the ld command
- * if this changes, also modify the code for ldCmdSpace
- */
- #define LoadCommandTemplate "/bin/ld -N -x -A %s -T %lx %s %s -o %s %s -lc"
-
- int
- loadhelp(objFile, relocFile, tmpFile, libString, otherString)
- char *objFile, *relocFile, *tmpFile, *libString, *otherString;
- {
- char *loadCommand; /* pointer to string containing the ld cmd */
- int ldCmdSpace; /* space allocated for ld command */
- char buf[BUFSIZ]; /* for buffering tmpFile i/o */
- struct exec hdr;
- long loadPoint, endOfMem, pageSize, tmp;
- FILE *tmpFD = NULL;
- long bytesToRead, bytesToExtend;
-
- /*
- * calculate the length of the ld command and allocate memory for it
- * this code would need changing if LoadCommandTemplate was changed
- */
- ldCmdSpace = strlen(LoadCommandTemplate);
- ldCmdSpace += strlen(objFile) + strlen(relocFile) + strlen(tmpFile);
- ldCmdSpace += strlen(libString) + strlen(otherString);
- ldCmdSpace += 16; /* 10 for loadPoint + 1 for null + fudge of 5 */
-
- #ifdef DEBUG
- (void)fprintf(stderr,"loadhelp: ld cmd needs %d bytes\n", ldCmdSpace);
- #endif DEBUG
-
- #ifdef USE_MALLOC
- loadCommand = malloc((unsigned)ldCmdSpace);
- #else ~USE_MALLOC
- loadCommand = alloca(ldCmdSpace);
- #endif ~USE_MALLOC
-
- if ((long)loadCommand == 0) {
- #ifdef DEBUG
- perror("loadhelp");
- (void)fprintf(stderr,
- "loadhelp: could not allocate %d bytes for ld cmd\n",
- ldCmdSpace);
- #endif DEBUG
- #ifdef USE_MALLOC
- free(loadCommand);
- #endif USE_MALLOC
- return(1);
- }
-
- pageSize = (long) getpagesize(); /* works on vaxen, suns, and mips */
- /* there is a strong assumption that pageSize is a power of 2 */
-
- #ifdef DEBUG
- (void)fprintf(stderr,"loadhelp: page size is %ld (%lx)\n", pageSize, pageSize);
- #endif DEBUG
-
- endOfMem = (long) sbrk(0); /* get end of current memory */
- if (endOfMem < 0) {
- #ifdef DEBUG
- perror("loadhelp");
- (void)fprintf(stderr,"loadhelp: sbrk(0) failed\n");
- #endif DEBUG
- #ifdef USE_MALLOC
- free(loadCommand);
- #endif USE_MALLOC
- return(2);
- }
-
- #ifdef DEBUG
- (void)fprintf(stderr,"loadhelp: end of memory = %ld (%lx)\n",
- endOfMem, endOfMem);
- #endif DEBUG
-
- /* round up to the next higher pageSize */
- loadPoint = (long) sbrk((int)(pageSize - (endOfMem & (pageSize - 1L))));
-
- if (loadPoint < 0L) {
- #ifdef DEBUG
- perror("loadhelp");
- (void)fprintf(stderr,"loadhelp: could not bump upto pagesize\n");
- #endif DEBUG
- #ifdef USE_MALLOC
- free(loadCommand);
- #endif USE_MALLOC
- return(3);
- }
-
- #ifdef mips
- loadPoint = (long) sbrk(0) + pageSize*4; /* Hack to counter change in break value after fopen */
- #else
- loadPoint = (long) sbrk(0);
- #endif
-
- /*
- * there had better be no further calls to sbrk explicitly or implicitly
- * (e.g. via calling printf or something like that) until the loading is
- * over.
- */
-
- /* sanity check */
- if (loadPoint < 0L || ((loadPoint & (pageSize - 1L)) != 0L)) {
- #ifdef DEBUG
- perror("loadhelp");
- (void)fprintf(stderr,"loadhelp: not page aligned\n");
- #endif DEBUG
- #ifdef USE_MALLOC
- free(loadCommand);
- #endif USE_MALLOC
- return(4);
- }
-
- #ifdef DEBUG
- (void)fprintf(stderr,"loadhelp: load point is %ld (%lx)\n",
- loadPoint, loadPoint);
- #endif DEBUG
-
- (void)sprintf(loadCommand, LoadCommandTemplate,
- relocFile, loadPoint, otherString, objFile, tmpFile, libString);
-
- /* if the sprintf overflows it'll probably botch BAD, but just in case */
- if (strlen(loadCommand) >= ldCmdSpace) {
- #ifdef DEBUG
- (void)fprintf(stderr,
- "loadhelp: load command greater than %d byte buffer\n",
- ldCmdSpace);
- #endif DEBUG
- #ifdef USE_MALLOC
- free(loadCommand);
- #endif USE_MALLOC
- return(5);
- }
-
- #ifdef DEBUG
- (void)fprintf(stderr,"loadhelp: the load command is \"%s\"\n", loadCommand);
- (void)fprintf(stderr,"loadhelp: Before ld break= %lx\n", sbrk(0));
- #endif DEBUG
-
- /* run the ld comand to do relocation */
- if (system(loadCommand) != 0 ) {
- #ifdef DEBUG
- perror("loadhelp");
- (void)fprintf(stderr,"loadhelp: error in executing the ld command\n");
- #endif DEBUG
- #ifdef USE_MALLOC
- free(loadCommand);
- #endif USE_MALLOC
- return(6);
- }
-
- #ifdef DEBUG
- (void)fprintf(stderr,"loadhelp: After ld break= %lx\n", sbrk(0));
- #endif DEBUG
-
- /* open the relocated file */
- tmpFD = fopen(tmpFile, "r");
- if (tmpFD == NULL ) {
- #ifdef DEBUG
- perror("loadhelp");
- (void)fprintf(stderr, "loadhelp: could not open %s for read\n",
- tmpFile);
- #endif DEBUG
- #ifdef USE_MALLOC
- free(loadCommand);
- #endif USE_MALLOC
- return(7);
- }
-
- #ifdef DEBUG
- (void)fprintf(stderr,"loadhelp: After fopen break= %lx\n", sbrk(0));
- #endif DEBUG
-
- /*
- * use buf to buffer tmpFile so that no mallocs can occur
- * since buf is automatic, tmpFD must be closed upon exit from this routine
- */
- (void)setbuf(tmpFD,buf);
-
- /* read its header */
- if (fread((char *)&hdr, sizeof(struct exec), 1, tmpFD) != 1) {
- #ifdef DEBUG
- perror("loadhelp");
- (void)fprintf(stderr,"loadhelp: error reading header of %s\n", tmpFile);
- if (fclose(tmpFD) == EOF) perror("loadhelp"); /* close tmp file */
- if (unlink(tmpFile)) perror("loadhelp"); /* remove it */
- #else ~DEBUG
- (void)fclose(tmpFD); /* close tmp file */
- (void)unlink(tmpFile); /* remove it */
- #endif ~DEBUG
- #ifdef USE_MALLOC
- free(loadCommand);
- #endif USE_MALLOC
- return(8);
- }
-
- #ifdef DEBUG
- (void)fprintf(stderr,"loadhelp: After fread break= %lx\n", sbrk(0));
- #endif DEBUG
-
- #ifdef mips
- if (BADMAG(hdr)) {
- #else
- if (N_BADMAG(hdr)) {
- #endif
- #ifdef DEBUG
- (void)fprintf(stderr,"loadhelp: bad magic number %o in %s\n",
- hdr.a_magic, tmpFile);
- if (fclose(tmpFD) == EOF) perror("loadhelp"); /* close tmp file */
- if (unlink(tmpFile)) perror("loadhelp"); /* remove it */
- #else ~DEBUG
- (void)fclose(tmpFD); /* close tmp file */
- (void)unlink(tmpFile); /* remove it */
- #endif ~DEBUG
- #ifdef USE_MALLOC
- free(loadCommand);
- #endif USE_MALLOC
- return(9);
- }
-
- #ifdef DEBUG
- (void)fprintf(stderr,
- "loadhelp: magic = %o, text = %ld(%lx), data = %ld(%lx), bss = %ld(%lx)\n",
- hdr.a_magic, hdr.a_text,
- hdr.a_text, hdr.a_data,
- hdr.a_data, hdr.a_bss, hdr.a_bss);
- #endif DEBUG
-
- bytesToRead = hdr.a_text + hdr.a_data;
- bytesToExtend = bytesToRead + hdr.a_bss;
-
- #ifdef DEBUG
- (void)fprintf(stderr,
- "loadhelp: going to read %ld bytes and extend by %ld bytes\n",
- bytesToRead, bytesToExtend);
- #endif DEBUG
-
- #ifdef mips
- tmp = (long) sbrk(0); /* check break */
-
- if (tmp <= loadPoint) /* No problem: we're still within preallocated change in break value */
- brk(loadPoint); /* so shift break */
- else {
- fprintf(stderr, "Load failed: break value changed by more than preallocated!\n");
- #ifdef DEBUG
- if (fclose(tmpFD) == EOF) perror("loadhelp"); /* close tmp file */
- if (unlink(tmpFile)) perror("loadhelp"); /* remove it */
- #else ~DEBUG
- (void)fclose(tmpFD); /* close tmp file */
- (void)unlink(tmpFile); /* remove it */
- #endif ~DEBUG
- #ifdef USE_MALLOC
- free(loadCommand);
- #endif USE_MALLOC
- return(11);
- }
- #endif
-
-
- /* get required memory */
- tmp = (long) sbrk((int)bytesToExtend);
- if (tmp < 0L) {
- #ifdef DEBUG
- perror("loadhelp");
- (void)fprintf(stderr,"loadhelp: not enough memory\n");
- if (fclose(tmpFD) == EOF) perror("loadhelp"); /* close tmp file */
- if (unlink(tmpFile)) perror("loadhelp"); /* remove it */
- #else ~DEBUG
- (void)fclose(tmpFD); /* close tmp file */
- (void)unlink(tmpFile); /* remove it */
- #endif ~DEBUG
- #ifdef USE_MALLOC
- free(loadCommand);
- #endif USE_MALLOC
- return(10);
- }
-
- /* some last sanity checks */
- if (tmp != loadPoint) {
- #ifdef DEBUG
- (void)fprintf(stderr,
- "loadhelp: load point is %ld (%lx) but sbrk returns %ld (%lx)\n",
- loadPoint, loadPoint, tmp, tmp);
- if (fclose(tmpFD) == EOF) perror("loadhelp"); /* close tmp file */
- if (unlink(tmpFile)) perror("loadhelp"); /* remove it */
- #else ~DEBUG
- (void)fclose(tmpFD); /* close tmp file */
- (void)unlink(tmpFile); /* remove it */
- #endif ~DEBUG
- #ifdef USE_MALLOC
- free(loadCommand);
- #endif USE_MALLOC
- return(11);
- }
-
-
- if (tmp & (pageSize - 1L)) {
- #ifdef DEBUG
- (void)fprintf(stderr,
- "loadhelp: allocated memory at %ld -not page aligned\n");
- if (fclose(tmpFD) == EOF) perror("loadhelp"); /* close tmp file */
- if (unlink(tmpFile)) perror("loadhelp"); /* remove it */
- #else ~DEBUG
- (void)fclose(tmpFD); /* close tmp file */
- (void)unlink(tmpFile); /* remove it */
- #endif ~DEBUG
- #ifdef USE_MALLOC
- free(loadCommand);
- #endif USE_MALLOC
- return(12);
- }
-
- /* go to beginning of text */
- #ifdef mips
- if (fseek(tmpFD,(long)N_TXTOFF(hdr.ex_f,hdr.ex_o),0) < 0) {
- #else
- if (fseek(tmpFD,(long)N_TXTOFF(hdr),0) < 0) {
- #endif
- #ifdef DEBUG
- perror("loadhelp");
- (void)fprintf(stderr,"loadhelp: fseek failed on %s\n", tmpFile);
- if (fclose(tmpFD) == EOF) perror("loadhelp"); /* close tmp file */
- if (unlink(tmpFile)) perror("loadhelp"); /* remove it */
- #else ~DEBUG
- (void)fclose(tmpFD); /* close tmp file */
- (void)unlink(tmpFile); /* remove it */
- #endif ~DEBUG
- #ifdef USE_MALLOC
- free(loadCommand);
- #endif USE_MALLOC
- return(13);
- }
-
-
- /* read the text and data segments in */
- if (fread((char *)loadPoint, 1, (int)bytesToRead, tmpFD) != (int)bytesToRead) {
- #ifdef DEBUG
- perror("loadhelp");
- (void)fprintf(stderr, "loadhelp: could not read data from %s\n",
- tmpFile);
- if (fclose(tmpFD) == EOF) perror("loadhelp"); /* close tmp file */
- if (unlink(tmpFile)) perror("loadhelp"); /* remove it */
- #else ~DEBUG
- (void)fclose(tmpFD); /* close tmp file */
- (void)unlink(tmpFile); /* remove it */
- #endif ~DEBUG
- #ifdef USE_MALLOC
- free(loadCommand);
- #endif USE_MALLOC
- return(14);
- }
-
-
- #ifdef DEBUG
- if (fclose(tmpFD) == EOF) perror("loadhelp");
- #else ~DEBUG
- (void)fclose(tmpFD);
- #endif ~DEBUG
-
- #ifdef USE_MALLOC
- free(loadCommand);
- #endif USE_MALLOC
-
- return(0);
- }
-
-
- /*
- * return the address of the function functionName in the namelist
- * of the file fileName.
- * the calling procedure had better make sure that fileName exists.
- */
-
- /* Defined in pmaxassist.c
- /*unsigned long
- /*nlistone(fileName,functionName)
- /*char *fileName, *functionName;
- /*{
- /*struct nlist nl[2];
- /*int rc;
- /*
- /*nl[1].n_un.n_name = '\0'; /* terminate the name list */
- /*nl[0].n_un.n_name = functionName; /* put the function name in */
- /*rc = nlist(fileName,nl); /* call nlist */
- /*if (rc < 0 || (nl[0].n_type == (unsigned char) 0 /* check for errors */
- /* && nl[0].n_value == (unsigned long) 0))
- /* return ((unsigned long) 0);
- /*if (nl[0].n_type & N_TEXT) /* if it is in the text segment i.e. is a function */
- /* return(nl[0].n_value); /* return the address */
- /*else
- /* return ((unsigned long) 0); /* not a function */
- /*}
- */
-